package oceanlife;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

import javax.swing.JPanel;

import oceanlife.pathfinding.DelaunayTriangleTranslator;
import oceanlife.pathfinding.Edge;
import oceanlife.pathfinding.Line2;
import oceanlife.pathfinding.Obstacles;
import oceanlife.pathfinding.Pillar;
import oceanlife.pathfinding.Pnt;
import oceanlife.pathfinding.PointGraph;
import oceanlife.pathfinding.RadialFace;
import oceanlife.pathfinding.SimpleObstacle;
import oceanlife.pathfinding.Triangle;
import oceanlife.pathfinding.Triangulation;



public class SimPanel extends JPanel{
	private ArrayList<Agent> agents = new ArrayList<Agent>();
	private Obstacles obs;
	private ArrayList<Line2> fineGraphLines = new ArrayList<Line2>();
	private ArrayList<SimpleObstacle> simpleObs = new ArrayList<SimpleObstacle>();
	
	private PointGraph fineGraph = new PointGraph();
	private PointGraph coarseGraph = new PointGraph();
	
	public Obstacles getObstacles() {
		return obs;
	}

	public void clear(){
		obs.clear();
		agents = new ArrayList<Agent>();
		fineGraphLines = new ArrayList<Line2>();
		fineGraph = new PointGraph();
		coarseGraph = new PointGraph();
		setSimpleObs(new ArrayList<SimpleObstacle>());
		this.repaint();
	}
	
	public SimPanel(Obstacles obs_inc) {
		obs = obs_inc;
	}

	public void paintComponent(Graphics g) {
		clear(g);
		Graphics2D g2d = (Graphics2D)g;
		g2d.draw(new Rectangle2D.Double(0,0,OLSet.getX_size()-1.0,OLSet.getY_size()-1.0));
		g2d.setColor(Color.gray);
		//for(int i = 0; i < obs.getPolygonCount(); i++){
		//	g2d.draw(obs.getPolygon(i));
		//	g2d.fill(obs.getPolygon(i));
		//}
		for(SimpleObstacle ob : obs.getSimpleObstacles()){
			g2d.setColor(Color.green);
			g2d.draw(ob.pathToPolygon());
			g2d.setColor(Color.gray);
			g2d.draw(ob.obstacleToPolygon());
			g2d.fill(ob.obstacleToPolygon());
		}
		
		Font font = new Font("Dialog", Font.PLAIN, 10);
		int offset = 0;
		g2d.setFont(font);
		g2d.setColor(Color.blue);
		for(Line2 line : fineGraphLines){
			g2d.draw(line);
		}

		for(Agent ag : agents){
			g2d.setColor(Color.green);
			//g2d.setColor(getFearColor(ag));
			g2d.fill(ag.getPositionGraphic());
			g2d.setColor(Color.black);
			g2d.draw(ag.getPositionGraphic());
			g2d.draw(ag.getDirectionGraphic());
			if(ag.obsPoints != null){
				g2d.setColor(Color.yellow);
				//for(RadialFace rf : ag.obsPoints){
				//	g2d.draw(new Ellipse2D.Double(rf.getPnt().coord(0)-3,rf.getPnt().coord(1)-3,6,6));
				//}
				//for(Line2 borderLine : ag.getPathArea().getAreaBorderLines()){
				//	g2d.draw(borderLine);
				//}
			}
			if(ag.getPath() != null){
				g2d.setColor(Color.red);
				Pnt[] pathPnts = ag.getPath().getPointsOnEdge();
				for(int i = 1; i < pathPnts.length;i++){
					g2d.draw(new Line2(pathPnts[i-1],pathPnts[i]));
				}
			}
			g2d.setColor(Color.black);
			if(ag.getIntermediateGoal() != null){
				g2d.draw(new Ellipse2D.Double(ag.getIntermediateGoal().coord(0)-3,ag.getIntermediateGoal().coord(1)-3,6,6));
			}
			/*if(ag.pathArea.getAreaBorder().size() != 0){
				g2d.setColor(Color.red);
				for(RadialFace rf : ag.pathArea.getAreaBorder()){
					g2d.draw(new Ellipse2D.Double(rf.getPnt().coord(0)-3,rf.getPnt().coord(1)-3,6,6));
					g2d.draw(rf.getBorderLine());
				}
			}*/
			//for(Pnt obsPnt : ag.obs){
				//Line2 line = new Line2(obsPnt,ag.getPosition());
				//g2d.draw(line); //????
			//}
		}
		//for(Line2 line : coarsePathGraph){
		//	g2d.draw(line);
		//}
/*		g2d.setColor(Color.red);
		for(int i = 0; i < obs.getObstacleCount(); i++){
			for(int j = 0; j < obs.getInputObstacles().get(i).length;j++){
				int k = j-1;
				if(k < 0){
					k = obs.getInputObstacles().get(i).length - 1;
				}
				Pnt pnt1 = obs.getInputObstacles().get(i)[j];
				Pnt pnt2 = obs.getInputObstacles().get(i)[k];
				g2d.draw(new Line2(pnt1,pnt2));
			}
		}*/
		g2d.setColor(Color.red);
		/*for(Pnt key : coarseGraph.getTheNeighbors().keySet()){
			for(Pnt key2 : coarseGraph.getTheNeighbors().get(key).keySet()){
				Edge edge = coarseGraph.getTheNeighbors().get(key).get(key2);
				Pnt[] pnts = edge.getPointsOnEdge();
				double totalLength = 0.0;
				for(int i = 0; i < pnts.length-1;i++){
					totalLength += pnts[i].distanceTo(pnts[i+1]);
				}
				int x = (int)((edge.getFirstPoint().coord(0)+edge.getLastPoint().coord(0))/2.0);
				int y = (int)((edge.getFirstPoint().coord(1)+edge.getLastPoint().coord(1))/2.0);
				g2d.drawString(((int)totalLength)+"",x,y);
			}
		}	*/
		/*int counter = 0;
		for(Pnt key : fineGraph.getTheNeighbors().keySet()){
			for(Pnt key2 : fineGraph.getTheNeighbors().get(key).keySet()){
				Edge edge = fineGraph.getTheNeighbors().get(key).get(key2);
				int x = (int)((edge.getFirstPoint().coord(0)+edge.getLastPoint().coord(0))/2.0);
				int y = (int)((edge.getFirstPoint().coord(1)+edge.getLastPoint().coord(1))/2.0);
				
				//draw radius circles
				double minDistRadius = edge.getClosestObstacle();
				//g2d.draw(new Ellipse2D.Double(x-minDistRadius,y-minDistRadius,minDistRadius*2,minDistRadius*2));
				//g2d.drawString(((int)edge.getWeight())+" "+(int)minDistRadius,x,y);
				
				//g2d.drawString(((int)edge.getAgentsOnEdge())+"",x,y);
				//for(int o = 0; o < obs.getPolygonCount(); o++){
				//	Pnt middle = edge.getFirstPoint().getMiddle(edge.getLastPoint());
				//	Pnt closest = obs.getClosestPoint(o, middle);
				//	Pnt drawMiddle = middle.getMiddle(closest);
				//	Line2 near = new Line2(middle,closest);
				//	g2d.drawString((int)near.length()+"", (int)drawMiddle.coord(0), (int)drawMiddle.coord(1));
					//Line2 near = obs.getClosestLine(o, new Line2(edge.getFirstPoint(),edge.getLastPoint()));
				//	g2d.drawLine((int)near.x1, (int)near.y1, (int)near.x2, (int)near.y2);
				//}
				//break;
			}
			//break;
		}*/
		//paint path for each agent
		/*for(Agent ag : agents){
			Pnt prevPnt = null;
			if(ag.getPath() != null){
				for(Pnt pathPnt : ag.getPath().getPointsOnEdge()){
					if(prevPnt == null){
						prevPnt = pathPnt;
					} else {
						Line2 line = new Line2(pathPnt,prevPnt);
						g2d.draw(line);
						prevPnt = pathPnt;
					}
				}
			}
		}*/

//		g2d.draw(new Ellipse2D.Double(300.0,200.0,20.0,20.0));
	}
	
	
	//determain fear color
	/*private Color getFearColor(Agent ag) {
		Color fearColor;
		double fearColorNum = ag.fear();
		if(fearColorNum > 0){
			if(fearColorNum > 3){
				fearColorNum = 3;
			}
			fearColor = new Color((float)1.0,(float)(1.0-fearColorNum/3.0),(float)(1.0-fearColorNum/3.0));
		} else {
			fearColorNum *= -1;
			if(fearColorNum > 3){
				fearColorNum = 3;
			}
			fearColor = new Color((float)(1.0-fearColorNum/3.0),(float)1.0,(float)(1.0-fearColorNum/3.0));
		}
		return fearColor;
	}*/

	protected void clear(Graphics g) {
		super.paintComponent(g);
	}
	
	public void updateFineGraph(PointGraph graph) {
		fineGraph = graph;
		fineGraphLines.clear();
		for(Pnt key : graph.getTheNeighbors().keySet()){
			for(Pnt key2 : graph.getTheNeighbors().get(key).keySet()){
				Edge edge = graph.getTheNeighbors().get(key).get(key2);
				Line2 line = new Line2(edge.getFirstPoint().coord(0), edge.getFirstPoint().coord(1), edge.getLastPoint().coord(0), edge.getLastPoint().coord(1));
				fineGraphLines.add(line);
			}
		}		
	}

	/*public void updateCoarsePathGraph(PointGraph graph) {
		coarseGraph = graph;
		coarsePathGraph.clear();
		for(Pnt key : graph.getTheNeighbors().keySet()){
			for(Pnt key2 : graph.getTheNeighbors().get(key).keySet()){
				Edge edge = graph.getTheNeighbors().get(key).get(key2);
				Line2 line = new Line2(edge.getFirstPoint().coord(0), edge.getFirstPoint().coord(1), edge.getLastPoint().coord(0), edge.getLastPoint().coord(1));
				coarsePathGraph.add(line);
			}
		}		
	}*/

	public PointGraph getFineGraph() {
		return fineGraph;
	}

	public PointGraph getCoarseGraph() {
		return coarseGraph;
	}

	public void setAgents(ArrayList<Agent> agentsInc) {
		agents = agentsInc;
	}

	public ArrayList<Agent> getAgents() {
		return agents;
	}

	public void readObsParams(ArrayList<Pillar> pillars, Double xOffset,Double yOffset, Double pillarSpacing) {
		simpleObs = new ArrayList<SimpleObstacle>();
		//obs.readObsParams(pillars, xOffset, yOffset, pillarSpacing);
		for(int i = 0; i < pillars.size(); i++){
			simpleObs.add(new SimpleObstacle(pillars.get(i).getPnts(xOffset+(pillarSpacing*i), yOffset)));
		}
		//add corridor walls
		Double wallExtraLength = 50.0;
		Double wallThickness = 20.0;
		simpleObs.add(new SimpleObstacle(new Pnt[]{new Pnt(xOffset-wallExtraLength,yOffset),
										 new Pnt(xOffset+(pillars.size()*pillarSpacing)+wallExtraLength,yOffset),
										 new Pnt(xOffset+(pillars.size()*pillarSpacing)+wallExtraLength,yOffset-wallThickness),
										 new Pnt(xOffset-wallExtraLength,yOffset-wallThickness)}));
		simpleObs.add(new SimpleObstacle(new Pnt[]{new Pnt(xOffset-wallExtraLength,yOffset+Pillar.maxPosition+wallThickness),
										 new Pnt(xOffset+(pillars.size()*pillarSpacing)+wallExtraLength,yOffset+Pillar.maxPosition+wallThickness),
										 new Pnt(xOffset+(pillars.size()*pillarSpacing)+wallExtraLength,yOffset+Pillar.maxPosition),
										 new Pnt(xOffset-wallExtraLength,yOffset+Pillar.maxPosition)}));

	}


	private void setSimpleObs(ArrayList<SimpleObstacle> simpleObstacles) {
		this.simpleObs = simpleObstacles;
	}

	public ArrayList<SimpleObstacle> getSimpleObs() {
		return simpleObs;
	}

}
